using System;
using TFlex;
using TFlex.Command;
using TFlex.Model;

namespace External3D
{
	// Identifiers of application commands
	//
	// Идентификаторы команд основного меню
	enum Commands
	{
		CreateCube = 1,
		CreateSphere
	};

	// Identifiers of commands provided by the cube creation automaton
	//
	// Идентификаторы команд автомата создания кубика
	enum CubeAutomenuCommands
	{
		// Select position of the cube center
		//
		// Выбрать центр куба
		CentrePoint,

		// Select direction of one of cube edges
		//
		// Выбрать направление одной стороны куба
		FirstEdgeDirection,

		// Select direction of another cube edge
		//
		// Выбрать направление другой стороны куба
		SecondEdgeDirection,

		// Cancel selected snaps
		//
		// Отменить привязку куба
		CancelSnaps
	};

	// Identifiers of commands provided by the sphere creation automaton
	//
	// Идентификаторы команд автомата создания сферы
	enum SphereAutomenuCommands
	{
		// Select position of the sphere center
		//
		// Выбрать центр сферы
		CentrePoint = CubeAutomenuCommands.CancelSnaps + 1,

		// Cancel selected snaps
		//
		// Отменить привязку сферы
		CancelSnaps
	};

	// Identifiers of context menu commands
	//
	// Команды контекстного меню
	enum ObjectCommands
	{
		EditCube = Commands.CreateSphere + 1,
		EditSphere
	};

	// Identifiers of object icons
	//
	// Иконки для внешних операций
	enum ObjectTypeIcons
	{
		CubeIcon,
		SphereIcon
	};

	// Identifiers of classes of objects created by this application
	//
	// Идентификаторы классов объектов внешнего приложения
	enum ObjectTypeIDs
	{
		CubeID,
		SphereID
	};

	// Class providing application properties and a method used to create an application object
	//
	// Класс с предопределенным именем Factory для создания экземпляра внешнего приложения
	public class Factory : PluginFactory
	{
		private static readonly Guid m_guid = new Guid("{9511BC0A-2BAE-4f98-88D1-D9A41FEC689E}");

		// Creates an application object
		//
		// Необходимо переопределить данный метод для создания объекта
		public override Plugin CreateInstance() { return new External3DPlugin(this); }

		// Unique identifier of this application
		//
		// Уникальный GUID приложения. Он должен быть обязательно разным у разных приложений
		public override Guid ID { get { return m_guid; } }

		// Name of this application
		//
		// Имя приложения
		public override string Name { get { return External3DPlugin.Resources.GetString("application_name"); } }
	};

	// Application class
	//
	// Класс внешнего приложения
	public class External3DPlugin : Plugin
	{
		internal static readonly System.Reflection.Assembly Assembly = typeof(External3DPlugin).Assembly;
		internal static readonly System.Resources.ResourceManager Resources
			= new System.Resources.ResourceManager("External3D.Properties.Resources", Assembly);

		public External3DPlugin(Factory factory)
			: base(factory)
		{
		}

		// Registers automenu commands
		//
		// Регистрирует команды автоменю
		protected override void OnInitialize()
		{
			base.OnInitialize();

			// Register commands of the cube creation automaton
			//
			// Зарегистрировать команды автомата создания кубика
			RegisterAutomenuCommand((int)CubeAutomenuCommands.CentrePoint,
			                        Resources.GetString("automenu.cube.select_center"),
			                        LoadIconResource("CubeAutomenu1"));
			RegisterAutomenuCommand((int)CubeAutomenuCommands.FirstEdgeDirection,
									Resources.GetString("automenu.cube.select_first_edge"),
			                        LoadIconResource("CubeAutomenu2"));
			RegisterAutomenuCommand((int)CubeAutomenuCommands.SecondEdgeDirection,
									Resources.GetString("automenu.cube.select_second_edge"),
			                        LoadIconResource("CubeAutomenu3"));
			RegisterAutomenuCommand((int)CubeAutomenuCommands.CancelSnaps,
			                        Resources.GetString("automenu.cancel_snaps"),
			                        LoadIconResource("CubeAutomenu4"));

			// Register commands of the sphere creation automaton
			//
			// Зарегистрировать команды автомата создания сферы
			RegisterAutomenuCommand((int)SphereAutomenuCommands.CentrePoint,
			                        Resources.GetString("automenu.sphere.select_center"),
			                        LoadIconResource("SphereAutomenu1"));
			RegisterAutomenuCommand((int)SphereAutomenuCommands.CancelSnaps,
			                        Resources.GetString("automenu.cancel_snaps"),
			                        LoadIconResource("SphereAutomenu2"));
		}

		// Registers application commands and creates user interface objects (menu items, tool bars, etc.)
		//
		// Регистрирует команды приложения и создаёт элементы пользовательского интерфейса
		protected override void OnCreateTools()
		{
			base.OnCreateTools();

			// Register application commands
			//
			// Зарегистрировать команды основного меню
			RegisterCommand((int)Commands.CreateCube,
			                Resources.GetString("commands.create_cube"),
			                LoadIconResource("CommandsSmall1"),
			                LoadIconResource("CommandsLarge1"));
			RegisterCommand((int)Commands.CreateSphere,
			                Resources.GetString("commands.create_sphere"),
			                LoadIconResource("CommandsSmall2"),
			                LoadIconResource("CommandsLarge2"));

			// Register context menu commands
			//
			// Зарегистрировать команды контекстного меню
			RegisterObjectCommand((int)ObjectCommands.EditCube,
			                      Resources.GetString("commands.edit_cube"),
			                      LoadIconResource("CommandsSmall1"),
			                      LoadIconResource("CommandsLarge1"));
			RegisterObjectCommand((int)ObjectCommands.EditSphere,
			                      Resources.GetString("commands.edit_sphere"),
			                      LoadIconResource("CommandsSmall2"),
			                      LoadIconResource("CommandsLarge2"));

			// Create application menu and add it to the CAD one
			//
			// Создание и добавление меню внешнего приложения в основное меню
			TFlex.Menu submenu = new TFlex.Menu();
			submenu.CreatePopup();
			submenu.Append((int)Commands.CreateCube, Resources.GetString("commands.create_cube"), this);
			submenu.Append((int)Commands.CreateSphere, Resources.GetString("commands.create_sphere"), this);

			TFlex.Application.Window.InsertPluginSubMenu(Name,
			                                             submenu,
			                                             TFlex.MainWindow.InsertMenuPosition.PluginSamples,
			                                             this);

			// Create tool bar
			//
			// Создаём панель инструментов
			int[] commandIds = new int[]
				{
					(int)Commands.CreateCube,
					(int)Commands.CreateSphere
				};
			CreateToolbar(Name, commandIds);

			// Register object icons
			//
			// Регистрация иконок внешних операций
			RegisterObjectTypeIcon((int)ObjectTypeIcons.CubeIcon, LoadIconResource("Cube"));
			RegisterObjectTypeIcon((int)ObjectTypeIcons.SphereIcon, LoadIconResource("Sphere"));
		}

		// Handles application commands
		//
		// Обработка команд основного меню
		protected override void OnCommand(Document document, int id)
		{
			switch ((Commands)id)
			{
			case Commands.CreateCube:
				{
					CubeCreateCommand command = new CubeCreateCommand(this);
					command.Run(document.ActiveView);
					break;
				}

			case Commands.CreateSphere:
				{
					SphereCreateCommand command = new SphereCreateCommand(this);
					command.Run(document.ActiveView);
					break;
				}

			default:
				base.OnCommand(document, id);
				break;
			}
		}

		// Determines availability of application commands.
		// Current implementation checks only presence of a document but it's possible, for example, check existence of
		// objects needed by the particular command
		//
		// Проверка доступности команд основного меню.
		// В текущей версии проверяется только наличие документа, но можно проверять, к примеру, наличие в документе
		// объектов, на основе которых задаётся команда
		protected override void OnUpdateCommand(CommandUI cmdUI)
		{
			if (cmdUI == null)
				return;

			if (cmdUI.Document == null)
			{
				cmdUI.Enable(false);
				return;
			}

			switch (cmdUI.ID)
			{
			case (int)Commands.CreateCube:
				// ...
				break;

			case (int)Commands.CreateSphere:
				// ...
				break;
			}

			cmdUI.Enable();
		}

		// Creates and returns an application object
		//
		// Функция создания объектов внешнего приложения
		protected override ProxyObject CreateObject(Document document, IntPtr ownerHandle, int typeID)
		{
			switch (typeID)
			{
			case (int)ObjectTypeIDs.CubeID:
				return new Cube(ownerHandle);

			case (int)ObjectTypeIDs.SphereID:
				return new Sphere(ownerHandle);

			default:
				return null;
			}
		}

		private void OnCloseDocument(Document document)
		{
		}

		// Loads and returns the specified icon from resources embedded into the assembly
		//
		// Загрузка значков, встроенных в сборку
		private System.Drawing.Icon LoadIconResource(string name)
		{
			System.IO.Stream stream = Assembly.GetManifestResourceStream("External3D.Resource_Files." + name + ".ico");
			return new System.Drawing.Icon(stream);
		}
	}
}
